package org.jeecg.modules.business.doc.outbound.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.BeanUtil;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceipt;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceiptLoadCheck;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceiptMaterial;
import org.jeecg.modules.business.doc.outbound.entity.vo.*;
import org.jeecg.modules.business.doc.outbound.mapper.WmsOutReceiptLoadCheckMapper;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptLoadCheckService;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptMaterialService;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptService;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTask;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskMaterial;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskPick;
import org.jeecg.modules.business.outbound.entity.vo.OutboundTaskPickInfoVO;
import org.jeecg.modules.business.outbound.entity.vo.RepertorySimpleVO;
import org.jeecg.modules.business.outbound.service.IWmsOutReceiptTaskService;
import org.jeecg.modules.flow.callback.delivery.util.CommonDeliveryTaskUtil;
import org.jeecg.modules.flow.callback.enums.DocumentStatusEnum;
import org.jeecg.modules.flow.callback.enums.SimpleDocumentTypeEnum;
import org.jeecg.modules.flow.callback.outbound.util.CommonOutboundUtil;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 出库单-装车复核
 * @Author: jeecg-boot
 * @Date: 2023-08-09
 * @Version: V1.0
 */
@RequiredArgsConstructor
@Service
public class WmsOutReceiptLoadCheckServiceImpl extends ServiceImpl<WmsOutReceiptLoadCheckMapper, WmsOutReceiptLoadCheck> implements IWmsOutReceiptLoadCheckService {


    private final WmsOutReceiptLoadCheckMapper loadCheckMapper;

    private final IWmsOutReceiptTaskService taskService;

    private final IWmsOutReceiptService receiptService;

    private final IWmsOutReceiptMaterialService receiptMaterialService;

    private final CommonOutboundUtil commonOutboundUtil;

    private final CommonDeliveryTaskUtil commonDeliveryTaskUtil;

    /**
     * 查询所有未复核信息
     * @param receiptId
     * @param materialName
     * @param batchCode
     * @return
     */
    @Override
    public IPage<OutboundReceiptLoadCheckFullVO> listAllUnCheck(IPage<WmsOutReceiptLoadCheck> page,String receiptId, String materialName, String batchCode, String carNumber) {

        IPage<OutboundReceiptLoadCheckFullVO> pageList=loadCheckMapper.listAllUnCheck(page,receiptId, materialName, batchCode,carNumber);
        List<OutboundReceiptLoadCheckFullVO> list = pageList.getRecords();
        if(!CollectionUtil.isEmpty(list)){
            for(OutboundReceiptLoadCheckFullVO fullVO:list){
                // 查询即时库存中的库区库位
                RepertorySimpleVO repertorySimpleVO = taskService.getMaterialRepertoryInfoByOutId(fullVO.getWmsOutReceiptTaskMaterialId());
                fullVO.setWmsBasicWarehouseId(repertorySimpleVO.getWmsBasicWarehouseId());
                fullVO.setWmsBasicWarehouseName(repertorySimpleVO.getWmsBasicWarehouseName());
                fullVO.setWmsBasicWarehouseAreaId(repertorySimpleVO.getWmsBasicWarehouseAreaId());
                fullVO.setWmsBasicWarehouseAreaName(repertorySimpleVO.getWmsBasicWarehouseAreaName());
                fullVO.setWmsBasicWarehouseAreaLocationId(repertorySimpleVO.getWmsBasicWarehouseAreaLocationId());
                fullVO.setWmsBasicWarehouseAreaLocationName(repertorySimpleVO.getWmsBasicWarehouseAreaLocationName());
            }
            pageList.setRecords(list);
        }
        return pageList;
    }

    /**
     * 查询所有已复核信息
     * @param receiptId
     * @param materialName
     * @param batchCode
     * @return
     */
    @Override
    public IPage<OutboundReceiptLoadCheckVO> listAllChecked(IPage<WmsOutReceiptLoadCheck> page,String receiptId, String materialName, String batchCode) {
        IPage<OutboundReceiptLoadCheckVO> pageList=loadCheckMapper.listAllChecked(page,receiptId, materialName, batchCode);
        return pageList;
    }

    /**
     * 增加复核信息
     * @param addLoadCheckVO
     */
    @Override
    public void addCheckInfo(OutboundAddLoadCheckVO addLoadCheckVO) {
        WmsOutReceiptTask wmsOutReceiptTask = taskService.getById(addLoadCheckVO.getWmsOutReceiptTaskId());
        WmsOutReceipt wmsOutReceipt = receiptService.getById(addLoadCheckVO.getWmsOutReceiptId());
        if(Objects.isNull(wmsOutReceiptTask)){
            throw new JeecgBootException("出库任务不存在");
        }
        if(Objects.isNull(wmsOutReceipt)){
            throw new JeecgBootException("出库单不存在");
        }
        Boolean needLoadCheckFlag = commonOutboundUtil.needLoadCheckFlag(addLoadCheckVO.getWmsOutReceiptTaskId());
        if(!needLoadCheckFlag){
            throw new JeecgBootException("该任务不能装车复核");
        }
        if(DocumentStatusEnum.COMPLETE.getCode().equals(wmsOutReceiptTask.getDocumentStatus())){
            throw new JeecgBootException("该任务已经完成");
        }
        if(DocumentStatusEnum.COMPLETE.getCode().equals(wmsOutReceipt.getDocumentStatus())){
            throw new JeecgBootException("该出库单已经完成");
        }
        List<OutboundLoadCheckInfoVO> loadCheckInfoVOList = addLoadCheckVO.getLoadCheckInfoVOList();
        boolean anyMatch = loadCheckInfoVOList.stream().anyMatch(o -> StrUtil.isEmpty(o.getWmsBasicWarehouseId()));
        if(anyMatch){
            throw new JeecgBootException("装车复核信息中有物料没有找到即时库存");
        }
        List<WmsOutReceiptLoadCheck> loadCheckList = BeanUtil.copyToList(loadCheckInfoVOList, WmsOutReceiptLoadCheck.class);
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String loginUserUsername = loginUser.getUsername();
        loadCheckList.stream().forEach(l->{
            l.setLoadPerson(loginUserUsername);
            l.setLoadTime(new Date());
            l.setLoadStatus("未出库");
        });
        //保存装车复核信息
        this.saveBatch(loadCheckList);
        //更新出库单物料信息
        //更新任务物料的装车复核数量
        loadCheckList.stream().forEach(l->{
            receiptMaterialService.update(new LambdaUpdateWrapper<WmsOutReceiptMaterial>()
                    .set(WmsOutReceiptMaterial::getHasLoadCheck,1)
                    .eq(WmsOutReceiptMaterial::getId,l.getWmsOutReceiptMaterialId())
            );
        });
        //更新调拨任务物料状态
        loadCheckList.stream().forEach(l->{
            commonDeliveryTaskUtil.updateMaterialDeliveryStatus(SimpleDocumentTypeEnum.OUT_TASK,l.getWmsOutReceiptTaskId(),l.getWmsOutReceiptTaskMaterialId(),"普天装车复核",null);
        });
    }

    /**
     * 取消复核
     * @param cancelLoadCheckVO
     */
    @Override
    public void cancelPick(OutboundCancelLoadCheckVO cancelLoadCheckVO) {
        WmsOutReceiptTask wmsOutReceiptTask = taskService.getById(cancelLoadCheckVO.getWmsOutReceiptTaskId());
        WmsOutReceipt wmsOutReceipt = receiptService.getById(cancelLoadCheckVO.getWmsOutReceiptId());
        if(Objects.isNull(wmsOutReceiptTask)){
            throw new JeecgBootException("出库任务不存在");
        }
        if(Objects.isNull(wmsOutReceipt)){
            throw new JeecgBootException("出库单不存在");
        }
        Boolean needLoadCheckFlag = commonOutboundUtil.needLoadCheckFlag(cancelLoadCheckVO.getWmsOutReceiptTaskId());
        if(!needLoadCheckFlag){
            throw new JeecgBootException("该任务不能装车复核");
        }
        if(DocumentStatusEnum.COMPLETE.getCode().equals(wmsOutReceiptTask.getDocumentStatus())){
            throw new JeecgBootException("该任务已经完成");
        }
        if(DocumentStatusEnum.COMPLETE.getCode().equals(wmsOutReceipt.getDocumentStatus())){
            throw new JeecgBootException("该出库单已经完成");
        }

        // 校验是否能取消拣货
        List<WmsOutReceiptLoadCheck> loadCheckList = this.listByIds(cancelLoadCheckVO.getCheckIdList());
        if(CollectionUtil.isEmpty(loadCheckList)){
            return;
        }
        //检查物料是否已经出库
        boolean anyMatch = loadCheckList.stream().anyMatch(p -> p.getLoadStatus().equals("已出库"));
        if(anyMatch){
            throw new JeecgBootException("存在已出库的物料，无法取消！");
        }
        // 装车复核
        // 删除装车复核数据
        this.removeByIds(cancelLoadCheckVO.getCheckIdList());
        // 更新任务物料的拣货数据
        loadCheckList.stream().forEach(p->{
            WmsOutReceiptMaterial receiptMaterial = receiptMaterialService.getById(p.getWmsOutReceiptMaterialId());
            if(!Objects.isNull(receiptMaterial)){
                receiptMaterial.setHasLoadCheck(0);
                receiptMaterialService.updateById(receiptMaterial);
            }
        });
    }

    /**
     * 根据任务物料id取消复核
     * @param cancelLoadCheckByIdVO
     */
    @Override
    public void cancelPickByTaskMaterialId(OutboundCancelLoadCheckByIdVO cancelLoadCheckByIdVO) {
        WmsOutReceiptTask wmsOutReceiptTask = taskService.getById(cancelLoadCheckByIdVO.getWmsOutReceiptTaskId());
        WmsOutReceipt wmsOutReceipt = receiptService.getById(cancelLoadCheckByIdVO.getWmsOutReceiptId());
        if(Objects.isNull(wmsOutReceiptTask)){
            throw new JeecgBootException("出库任务不存在");
        }
        if(Objects.isNull(wmsOutReceipt)){
            throw new JeecgBootException("出库单不存在");
        }
        Boolean needLoadCheckFlag = commonOutboundUtil.needLoadCheckFlag(cancelLoadCheckByIdVO.getWmsOutReceiptTaskId());
        if(!needLoadCheckFlag){
            throw new JeecgBootException("该任务不能装车复核");
        }
        if(DocumentStatusEnum.COMPLETE.getCode().equals(wmsOutReceiptTask.getDocumentStatus())){
            throw new JeecgBootException("该任务已经完成");
        }
        if(DocumentStatusEnum.COMPLETE.getCode().equals(wmsOutReceipt.getDocumentStatus())){
            throw new JeecgBootException("该出库单已经完成");
        }

        // 校验是否能取消拣货
        List<WmsOutReceiptLoadCheck> loadCheckList = this.list(new LambdaQueryWrapper<WmsOutReceiptLoadCheck>()
                .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptTaskId,cancelLoadCheckByIdVO.getWmsOutReceiptTaskId())
                .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptId,cancelLoadCheckByIdVO.getWmsOutReceiptId())
                .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptMaterialId,cancelLoadCheckByIdVO.getWmsOutReceiptMaterialId())
        );
        if(CollectionUtil.isEmpty(loadCheckList)){
            return;
        }
        //检查物料是否已经出库
        boolean anyMatch = loadCheckList.stream().anyMatch(p -> p.getLoadStatus().equals("已出库"));
        if(anyMatch){
            throw new JeecgBootException("存在已出库的物料，无法取消！");
        }
        // 装车复核
        // 删除装车复核数据
        List<String> loadCheckIdList = loadCheckList.stream().map(o -> o.getId()).collect(Collectors.toList());
        this.removeByIds(loadCheckIdList);
        // 更新任务物料的拣货数据
        loadCheckList.stream().forEach(p->{
            WmsOutReceiptMaterial receiptMaterial = receiptMaterialService.getById(p.getWmsOutReceiptMaterialId());
            if(!Objects.isNull(receiptMaterial)){
                receiptMaterial.setHasLoadCheck(0);
                receiptMaterialService.updateById(receiptMaterial);
            }
        });
    }

    /**
     * 复核出库
     * @param checkId
     */
    @Override
    public void checkOut(String checkId) {
        WmsOutReceiptLoadCheck loadCheck = this.getById(checkId);
        if(Objects.isNull(loadCheck)){
            throw new JeecgBootException("装车复核信息不存在");
        }
        loadCheck.setLoadStatus("已出库");
        this.updateById(loadCheck);
    }

    /**
     * 装车复核时扫码查询待装车复核物料
     * @param name
     * @param receiptId
     * @return
     */
    @Override
    public List<OutboundReceiptLoadCheckFullVO> getLoadCheckByNameAndTaskId(String name, String receiptId) {

        List<OutboundReceiptLoadCheckFullVO> list=loadCheckMapper.listAllUnCheckByCode(receiptId, name);
        //过滤钓已经装车复核的数据
        List<OutboundReceiptLoadCheckFullVO> collect = list.stream().filter(o -> Objects.isNull(o.getHasLoadCheck()) || !o.getHasLoadCheck()).collect(Collectors.toList());
        //查询即时库存
        if(!CollectionUtil.isEmpty(collect)){
            for(OutboundReceiptLoadCheckFullVO fullVO:collect){
                // 查询即时库存中的库区库位
                RepertorySimpleVO repertorySimpleVO = taskService.getMaterialRepertoryInfoByOutId(fullVO.getWmsOutReceiptTaskMaterialId());
                fullVO.setWmsBasicWarehouseId(repertorySimpleVO.getWmsBasicWarehouseId());
                fullVO.setWmsBasicWarehouseName(repertorySimpleVO.getWmsBasicWarehouseName());
                fullVO.setWmsBasicWarehouseAreaId(repertorySimpleVO.getWmsBasicWarehouseAreaId());
                fullVO.setWmsBasicWarehouseAreaName(repertorySimpleVO.getWmsBasicWarehouseAreaName());
                fullVO.setWmsBasicWarehouseAreaLocationId(repertorySimpleVO.getWmsBasicWarehouseAreaLocationId());
                fullVO.setWmsBasicWarehouseAreaLocationName(repertorySimpleVO.getWmsBasicWarehouseAreaLocationName());
            }
        }
        return collect;
    }
}
